package org.example.curriculum_design_6_16.controller;

import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.example.curriculum_design_6_16.common.auth.AccessDeniedException;
import org.example.curriculum_design_6_16.common.system.SystemException;
import org.example.curriculum_design_6_16.entity.dto.GradeFormDTO;
import org.example.curriculum_design_6_16.entity.pojo.Course;
import org.example.curriculum_design_6_16.entity.pojo.Grade;
import org.example.curriculum_design_6_16.entity.pojo.Student;
import org.example.curriculum_design_6_16.entity.vo.GradeVo;
import org.example.curriculum_design_6_16.entity.vo.Result;
import org.example.curriculum_design_6_16.service.CourseService;
import org.example.curriculum_design_6_16.service.GradeService;
import org.example.curriculum_design_6_16.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/grade")
public class GradeController {

    @Autowired
    private GradeService gradeService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private StudentService studentService;

    @Autowired
    public GradeController(GradeService gradeService) {
        this.gradeService = gradeService;
    }

    @ApiOperation("添加成绩")
    @PostMapping
    public Result addGrade(@RequestBody @Validated GradeFormDTO gradeFormDTO) {
        try {
            if (gradeService.existsGradeForStudentAndCourse(gradeFormDTO.getStudentId(), gradeFormDTO.getCourseId())) {
                return Result.fail(409, "该学生此课程成绩已存在");
            }

            Grade grade = new Grade();
            grade.setStudentId(gradeFormDTO.getStudentId());
            grade.setCourseId(gradeFormDTO.getCourseId());
            grade.setScore(gradeFormDTO.getScore());
            grade.setSemester(gradeFormDTO.getSemester());

            boolean success = gradeService.addGrade(grade);
            if (success) {
                return Result.success("成绩添加成功");
            }
            return Result.fail(500, "成绩添加失败");
        } catch (AccessDeniedException e) {
            throw new AccessDeniedException();
        } catch (Exception e) {
            log.error("添加成绩失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_001", "添加成绩失败，请稍后再试");
        }
    }

    @ApiOperation("更新成绩")
    @PutMapping("/update")
    public Result updateGrade(@RequestBody @Validated GradeFormDTO gradeFormDTO) {
        try {
            String studentId = gradeFormDTO.getStudentId();
            String courseId = gradeFormDTO.getCourseId();

            Grade existingGrade = gradeService.getGradeById(studentId, courseId);
            if (existingGrade == null) {
                return Result.fail(404, "成绩记录不存在");
            }

            Grade grade = new Grade();
            grade.setStudentId(gradeFormDTO.getStudentId());
            grade.setCourseId(gradeFormDTO.getCourseId());
            grade.setScore(gradeFormDTO.getScore());
            grade.setSemester(gradeFormDTO.getSemester());
            boolean success = gradeService.updateGrade(grade);
            if (success) {
                return Result.success("成绩更新成功");
            }
            return Result.fail(500, "成绩更新失败");
        } catch (AccessDeniedException e) {
            throw new AccessDeniedException();
        } catch (Exception e) {
            log.error("更新成绩失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_002", "更新成绩失败，请稍后再试");
        }
    }

    @ApiOperation("删除成绩")
    @DeleteMapping("/del")
    public Result deleteGrade(@RequestParam String studentId, @RequestParam String courseId) {
        try {
            Grade existingGrade = gradeService.getGradeById(studentId, courseId);
            if (existingGrade == null) {
                return Result.fail(404, "成绩记录不存在");
            }

            boolean success = gradeService.deleteGradeById(existingGrade.getId());
            if (success) {
                return Result.success("成绩删除成功");
            }
            return Result.fail(500, "成绩删除失败");
        } catch (AccessDeniedException e) {
            throw new AccessDeniedException();
        } catch (Exception e) {
            log.error("删除成绩失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_003", "删除成绩失败，请稍后再试");
        }
    }


    @ApiOperation("获取学生所有成绩")
    @GetMapping("/student/{studentId}")
    public Result getGradesByStudent(@PathVariable String studentId) {
        try {
            List<Grade> grades = gradeService.getGradesByStudentId(studentId);
            List<GradeVo> gradeVOs = new ArrayList<>();
            for (Grade grade : grades) {
                String courseName = courseService.getCourseById(grade.getCourseId()).getCourseName();
                GradeVo gradeVo = new GradeVo();
                gradeVo.buildGradeVo(grade, courseName);
                gradeVOs.add(gradeVo);
            }
            return Result.success(gradeVOs);
        } catch (Exception e) {
            log.error("获取学生成绩失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_005", "获取学生成绩失败，请稍后再试");
        }
    }

    @ApiOperation("获取课程所有成绩")
    @GetMapping("/course")
    public Result getGradesByCourse(@RequestParam String courseId) {
        try {
            List<Grade> grades = gradeService.getGradesByCourseId(courseId);
            List<GradeVo> gradeVOs = new ArrayList<>();
            for (Grade grade : grades) {
                String courseName = courseService.getCourseById(grade.getCourseId()).getCourseName();
                GradeVo gradeVo = new GradeVo();
                gradeVo.buildGradeVo(grade, courseName);
                gradeVOs.add(gradeVo);
            }
            return Result.success(gradeVOs);
        } catch (Exception e) {
            log.error("获取课程成绩失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_006", "获取课程成绩失败，请稍后再试");
        }
    }

    @ApiOperation("获取课程平均分")
    @GetMapping("/course/{courseId}/average")
    public Result getCourseAverage(@PathVariable String courseId) {
        try {
            Double average = gradeService.getAverageGradeByCourse(courseId);
            return Result.success(average);
        } catch (Exception e) {
            log.error("获取课程平均分失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_007", "获取课程平均分失败，请稍后再试");
        }
    }

    @ApiOperation("更新成绩备注")
    @PatchMapping("/{id}/remark")
    public Result updateRemark(@PathVariable Integer id, @RequestParam String remark) {
        try {
            boolean success = gradeService.updateGradeRemark(id, remark);
            if (success) {
                return Result.success("备注更新成功");
            }
            return Result.fail(500, "备注更新失败");
        } catch (Exception e) {
            log.error("更新成绩备注失败: {}", e.getMessage(), e);
            throw new SystemException("GRADE_008", "更新成绩备注失败，请稍后再试");
        }
    }

    @ApiOperation("计算奖学金学业成绩")
    @GetMapping("/academicAchievement/{studentId}")
    public Result getAcademicAchievement(@PathVariable String studentId) {
        try {
            List<Student> gradeStudents = studentService.getStudentGrade(2);
            boolean isInGrade2 = gradeStudents.stream()
                    .anyMatch(s -> studentId.equals(s.getStudentId()));

            if (!isInGrade2) {
                return Result.fail(404, "学生年级不符");
            }

            List<Grade> grades = gradeService.getGradesByStudentIdEFF(studentId);
            if (grades.isEmpty()) {
                return Result.fail(404, "该学生无成绩记录");
            }

            double average = grades.stream()
                    .mapToDouble(Grade::getScore)
                    .average()
                    .orElse(0);

            // 3. 计算学业成绩（20%）并保留6位小数
            BigDecimal maxScore = new BigDecimal("20");
            BigDecimal result = BigDecimal.valueOf(average * 0.2)
                    .setScale(6, RoundingMode.HALF_UP)
                    .min(maxScore);

            return Result.success(result);
        } catch (Exception e) {
            log.error("计算学业成绩失败 - 学号: {}", studentId, e);
            throw new SystemException("SCHOLARSHIP_001", "计算学业成绩失败");
        }
    }
}